package com.celesea.workflow.core.service;

import com.celesea.framework.authority.User;
import com.celesea.framework.dao.Filter;
import com.celesea.framework.service.AbstractBaseService;
import com.celesea.framework.util.*;
import com.celesea.workflow.WorkflowNoticeFactory;
import com.celesea.workflow.core.dao.WorkflowInstanceDao;
import com.celesea.workflow.core.entity.*;
import com.celesea.workflow.core.vo.BaseFlowVo;
import com.celesea.workflow.core.vo.WorkflowFilter;
import com.google.common.collect.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.util.List;

/**
 * @author JackYuan
 * @create 2017-11-28 16:03
 */
@Service
public class WorkflowInstanceServiceImpl extends
        AbstractBaseService<WorkflowInstance> implements WorkflowInstanceService {

    @Autowired
    private WorkflowPermissionService workflowPermissionService;
    @Autowired
    private WorkflowInstanceDao workflowInstanceDao;
    @Autowired
    private WorkflowNodeService workflowNodeService;
    @Autowired
    private WorkflowNodeActionService workflowNodeActionService;
    @Autowired
    private WorkflowNodePermissionService workflowNodePermissionService;
    @Autowired
    private WorkflowNoticeService workflowNoticeService;

    @Override
    public PageData<WorkflowInstance> selectWorkflow(WorkflowFilter filter, Page page, Sort sort) {
        String applyId = EnvUtil.getLoginUser().getId();
        List<Integer> status = Lists.newArrayList(
                WorkflowStatus.PROCESS.getCode(),
                WorkflowStatus.COMPLETE.getCode(),
                WorkflowStatus.END.getCode(),
                WorkflowStatus.ERROR.getCode()
        );
        return super.selectPageData(filter, page, sort, new PageProvider<WorkflowInstance>() {
            @Override
            public com.github.pagehelper.Page<WorkflowInstance> provider(Filter workflowFilter, Page page, Sort sort) {
                com.github.pagehelper.Page<WorkflowInstance> pageData = null;
                WorkflowFilter filter = (WorkflowFilter) workflowFilter;
                if (WorkflowView.DRAFT.equals(filter.getStatusFlag())) {
                    // 草稿状态
                    filter.setWorkflowStatus(Lists.newArrayList(WorkflowStatus.DRAFT.getCode()));
                    filter.setApplyId(hasStatisticsPerm(filter) ? null : applyId);
                    pageData = workflowInstanceDao.selectPage(filter, page, sort);
                } else if (WorkflowView.INITIATOR.equals(filter.getStatusFlag())) {
                    filter.setWorkflowStatus(status);
                    // 当前人
                    filter.setApplyId(applyId);
                    pageData = workflowInstanceDao.selectPage(filter, page, sort);

                } else if (WorkflowView.HANDLE.equals(filter.getStatusFlag())) {
                    // 我处理过的
                    filter.setWorkflowStatus(status);
                    filter.setApplyId(hasStatisticsPerm(filter) ? null : applyId);
                    pageData = workflowInstanceDao.selectJoin(filter, page, sort);
                } else {
                    // 我处理过的
                    filter.setWorkflowStatus(null);
                    filter.setApplyId(hasStatisticsPerm(filter) ? null : applyId);
                    pageData = workflowInstanceDao.selectJoin(filter, page, sort);
                }
                return pageData;
            }
        });
    }

    private boolean hasStatisticsPerm(WorkflowFilter filter) {
        return workflowPermissionService.hasStatisticsPerm(filter.getWorkflowType());
    }

    @Override
    public WorkflowInstance createWokflowInstance(WorkflowInstance instance) {
        boolean isSubmitAble = workflowPermissionService.hasSubmitPerm(instance.getWfType());
        Assert.isTrue(isSubmitAble,"没有提交权限！");
        super.insert(instance);
        // 修改为异步通知
        WorkflowNotice notice = WorkflowNoticeFactory.draftNotice(instance);
        workflowNoticeService.insert(notice);
        return instance;
    }

    @Override
    public WorkflowInstance updateWokflowInstance(BaseFlowVo flow, Workflow entity) {
        //TODO  检查权限,合法性
        WorkflowInstance instance = super.selectById(flow.getInstanceId());

        WorkflowNode nextNode = getNextNode(flow, instance);
        instance.activeWorkflowNode(nextNode);
        super.update(instance);
        // 修改为异步通知
        List<User> users = getNextPermissionUsers(nextNode, entity);
        if (CollectionKit.isNotEmpty(users)) {
            List<WorkflowNotice> notices = WorkflowNoticeFactory.processNotice(instance, users);
            workflowNoticeService.insertList(notices);
        }
        return instance;
    }

    private List<User> getNextPermissionUsers(WorkflowNode nextNode, Workflow entity) {
        List<WorkflowNodePermission> permissions = workflowNodePermissionService.selectByNode(nextNode);
        List<User> users = Lists.newArrayList();
        permissions.stream().forEach(item ->
                users.addAll(workflowNodePermissionService.parsePermissionUser(item, entity)));
        boolean isProcess = nextNode.getStatus() == WorkflowStatus.PROCESS.getCode()
                || nextNode.getStatus() == WorkflowStatus.DRAFT.getCode();
        if (isProcess) {
            // l流程中的节点用不不能为空
            Assert.isTrue(CollectionKit.isNotEmpty(users), "工作流节点用户不能为空！");
        }
        return users;
    }

    private WorkflowNode getNextNode(BaseFlowVo flow, WorkflowInstance instance) {
        WorkflowNodeAction action = workflowNodeActionService.selectById(flow.getActionId());
        Assert.notNull(action, "不存在的流程操作");
        Assert.notNull(action.getWfNodeId(), "不存在的流程操作");
        Assert.isTrue(action.getWfNodeId().equals(instance.getActiveNodeId()), "非法的流程操作");
        // next node
        WorkflowNode node = workflowNodeService.selectById(action.getToNodeId());
        Assert.notNull(node, "非法的流程操作");
        return node;
    }
}
